package com.huilian.iotbox.client.controller;

import com.huilian.iotbox.client.security.jwt.util.JwtTokenUtil;
import com.huilian.iotbox.client.service.*;
import com.huilian.iotbox.client.service.pay.PayService;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.controller.BaseController;
import com.huilian.iotbox.data.dto.*;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.utils.MD5SignUtil;
import com.huilian.iotbox.data.vo.CommodityStoreUpDownVo;
import com.huilian.iotbox.data.vo.DeviceVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author 谢洛涛
 * @date 2021/1/9 11:33
 */
@Slf4j
@RestController
@RequestMapping("/api/order")
public class OrderController extends BaseController {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private OrderService orderService;
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private BlackListService blackListService;
    @Autowired
    private Map<String, PayService> payServiceMap;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private CommodityStoreUpDownService commodityStoreUpDownService;


    /**
     * 支付回调
     *
     * @param request
     * @return
     */
    @PostMapping("/payNotice")
    public String payNotice(HttpServletRequest request) {
        try {
            return orderService.payNotice(request);
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            errorLogCommonService.writerInfoException("处理订单回调失败", null, e);
            return "error";
        }
    }



    /**
     * 线下收款码付款
     *
     * @param orderDto
     * @param request
     * @return
     * @throws Exception
     */
    @PostMapping("/offlinePay")
    public ServerResponse offlinePay(@RequestBody OrderDto orderDto, HttpServletRequest request) throws Exception {
        final MemberDto member = jwtTokenUtil.getMemberFromReq(request);

        if (StringUtils.isEmpty(orderDto.getMerchantStoreId())) {
            return ServerResponse.createByErrorMessage("merchantStoreId不能为空");
        }

        if (StringUtils.isEmpty(orderDto.getTotalAmount())) {
            return ServerResponse.createByErrorMessage("totalAmount不能为空");
        }

        if (orderDto.getTotalAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return ServerResponse.createByErrorMessage("totalAmount不能小于等于0");
        }

        ServerResponse checkMemberState = blackListService.checkMemberStateByMemberIdAndMerchantStoreId(member.getId(), orderDto.getMerchantStoreId());
        if (!checkMemberState.getIsSuccess()) {
            return checkMemberState;
        }

        List<DeviceVo> deviceList = deviceService.findDeviceByMerchantStoreId(orderDto.getMerchantStoreId());
        if (StringUtils.isEmpty(deviceList) || deviceList.size() == 0) {
            return ServerResponse.createByErrorMessage("当前场地未绑定设备，暂不支持使用线下收款码");
        }

        PayService offlinePayService = payServiceMap.get("offlinePayService");

        orderDto.setMemberId(member.getId());
        orderDto.setOpenId(member.getOpenId());

        offlinePayService.verification(orderDto, member.getId());
        offlinePayService.orderGen(orderDto, request);
        return ServerResponse.createBySuccess(offlinePayService.reqPay(orderDto, member));
    }

    @PostMapping("/vendingMachinePay")
    public ServerResponse vendingMachinePay(@RequestBody OrderDto orderDto, HttpServletRequest request) throws Exception {
        final MemberDto member = jwtTokenUtil.getMemberFromReq(request);
        PayService vendingMachinePayService = payServiceMap.get("VendingMachinePayService");

        DeviceDto device = deviceService.queryByDeviceNo(orderDto.getDeviceNo());
        ServerResponse checkMemberState = blackListService.checkMemberStateByMemberIdAndMerchantStoreId(member.getId(), device.getMerchantStoreId());
        if (!checkMemberState.getIsSuccess()) {
            return checkMemberState;
        }

        orderDto.setMerchantStoreId(device.getMerchantStoreId());
        orderDto.setDeviceId(device.getId());
        orderDto.setProductDisplayType(device.getProductDisplayType());
        orderDto.setShoppingCart(device.getShoppingCart());
        orderDto.setOpenId(member.getOpenId());
        orderDto.setMemberId(member.getId());
        orderDto.setAgencyId(device.getAgencyId());
        orderDto.setIsBluetooth(device.getIsBluetooth());

        vendingMachinePayService.deviceVerification(device, orderDto);
        vendingMachinePayService.verification(orderDto, member.getId());
        vendingMachinePayService.orderGen(orderDto, device, request);
        return ServerResponse.createBySuccess(vendingMachinePayService.reqPay(orderDto, member));
    }

    /**
     * 售货机付款码支付
     */
    @PostMapping("/vendingMachineScanPay")
    public ServerResponse vendingMachineScanPay(@RequestBody OrderDto orderDto, HttpServletRequest request) throws Exception {
        if (StringUtils.isEmpty(orderDto.getDeviceNo())) {
            return ServerResponse.createByErrorMessage("deviceNo不能为空");
        }

        if (StringUtils.isEmpty(orderDto.getTimestamp())) {
            return ServerResponse.createByErrorMessage("timestamp不能为空");
        }

        if (StringUtils.isEmpty(orderDto.getQrCodeUrl())) {
            return ServerResponse.createByErrorMessage("qrCodeUrl不能为空");
        }

        if (StringUtils.isEmpty(orderDto.getSign())) {
            return ServerResponse.createByErrorMessage("sign不能为空");
        }
        if (StringUtils.isEmpty(orderDto.getAttParams())) {
            return ServerResponse.createByErrorMessage("attParams不能为空");
        }
        List<CommodityStoreUpDownVo> commodityByAtt = (List<CommodityStoreUpDownVo>) commodityStoreUpDownService.getAllCommodityByAtt(orderDto.getDeviceNo(), URLDecoder.decode(orderDto.getAttParams(), "UTF-8")).getData();
        orderDto.setDeviceDtoList(new ArrayList<>());
        for (CommodityStoreUpDownVo c : commodityByAtt) {
            DeviceDto deviceDto = DeviceDto.builder()
                    .freightLane(c.getFreightLane())
                    .hierarchy(c.getHierarchy())
                    .displayRackItemId(c.getDisplayRackItemId())
                    .stock(c.getStock())
                    .commodityId(c.getCommodityId())
                    .cName(c.getCName())
                    .fileName(c.getFileName())
                    .retailPrice(c.getRetailPrice())
                    .num(c.getNum())
                    .commodityStoreUpDownId(c.getCommodityStoreUpDownId())
                    .productDisplayType(c.getProductDisplayType())
                    .build();
            orderDto.getDeviceDtoList().add(deviceDto);
        }
        log.info("解码获取到的商品集合:{}", commodityByAtt);
        Map<String, Object> params = new HashMap<>();
        params.put("deviceNo", orderDto.getDeviceNo());
        params.put("timestamp", orderDto.getTimestamp());
        params.put("discountId", orderDto.getDiscountId());
        params.put("qrCodeUrl", orderDto.getQrCodeUrl());
        params.put("attParams", orderDto.getAttParams());
        String checkSign = MD5SignUtil.signTopRequestByMap(params, MD5SignUtil.secret);
        if (!orderDto.getSign().equalsIgnoreCase(checkSign)) {
            return ServerResponse.createByErrorMessage("校验不通过");
        }

        final String key = String.format(RedisKey.REVERSE_SCAN_PAY_QR, orderDto.getQrCodeUrl());
        log.info("format{}", key);
        final String qrCodeUrl = (String) redisCacheTemplate.opsForValue().get(key);
        log.info("qrCodeUrl{}", qrCodeUrl);
        if (StringUtils.isEmpty(qrCodeUrl)) {
            redisCacheTemplate.opsForValue().set(key, orderDto.getQrCodeUrl(), 10, TimeUnit.SECONDS);
        } else {
            return ServerResponse.createByErrorMessage("请勿重复扫码");
        }
        PayService reverseScanPayService = payServiceMap.get("VendingMachinePayService");

        DeviceDto device = deviceService.queryByDeviceNo(orderDto.getDeviceNo());
        orderDto.setMerchantStoreId(device.getMerchantStoreId());
        orderDto.setDeviceId(device.getId());
        reverseScanPayService.deviceVerification(device, orderDto);
        reverseScanPayService.verification(orderDto, null);
        reverseScanPayService.orderGen(orderDto, device, request);
        return reverseScanPayService.reverseScanReqPay(orderDto, request);
    }
}
